package org.ftc.report;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

import org.apache.commons.lang3.StringUtils;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.model.fields.merge.DataFieldName;
import org.docx4j.model.fields.merge.MailMerger;
import org.docx4j.model.fields.merge.MailMerger.OutputField;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.FooterReference;
import org.docx4j.wml.Ftr;
import org.docx4j.wml.HdrFtrRef;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.R;
import org.docx4j.wml.STBrType;
import org.docx4j.wml.SectPr;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Tc;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;
import org.ftc.domain.Motion;

public class Report10 {

	static String[] NUM = { "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", //
			"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", //
			"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", //
			"1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
	static String[] CHINESE_NUM = { "三十", "三十一", "三十二", "三十三", "三十四", "三十五", "三十六", "三十七", "三十八", "三十九", //
			"二十", "二十一", "二十二", "二十三", "二十四", "二十五", "二十六", "二十七", "二十八", "二十九", //
			"十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", //
			"一", "二", "三", "四", "五", "六", "七", "八", "九", "０" };

	public static void main(String[] args) throws Exception {
		report8();
	}

	private static void report8() throws Exception {
		File tmp = new File("D:\\ftc\\1165\\錄案通知2.docx");
		WordprocessingMLPackage template = WordprocessingMLPackage.load(tmp);

		File tmp2 = new File("D:\\ftc\\1165\\錄案通知3.docx");
		WordprocessingMLPackage temp = WordprocessingMLPackage.load(tmp2);
		
		Part tempPart = template.getMainDocumentPart();
		List<Object> tables = getAllElementFromObject(tempPart, Tbl.class);
		System.out.println(tables.size());
		Tbl formatTable = getTemplateTable(tables, "公平交易委員會委員會議議決事項錄案通知書");
		System.out.println(formatTable.getParent().toString());
		System.out.println("index:"+template.getMainDocumentPart().getContent().indexOf(formatTable));
		
		Map<String, String> map = new HashMap<>();
		for (int x = 0; x < 5; x++) {
			Tbl tempTbl = XmlUtils.deepCopy(formatTable);
			map.put("session", "第1111次委員會議");
			map.put("unita", "測試");
			replaceAndAddTable(tempTbl, Arrays.asList(map), 1);
			map.put("date", "測試");
			map.put("unitb", "測試");
			replaceAndAddTable(tempTbl, Arrays.asList(map), 1);
			map.put("case", "測試案");
			map.put("cause", "測試測試");
			replaceAndAddTable(tempTbl, Arrays.asList(map), 1);
			map.put("r", "測試案");
			genDecide(tempTbl, Arrays.asList(map), 1);
			replaceAndAddTable(tempTbl, Arrays.asList(map), 1);
			if (x == 0) {
				temp.getMainDocumentPart().getContent().set(0, tempTbl);
			} else {
				temp.getMainDocumentPart().getContent().add(tempTbl);
				addPageBreak(temp);
			}
			
		}
		temp.save(new java.io.File("D:\\REPORT_10.docx"));
		System.out.println("end");
	}

	private static void replaceTable(String placeholders, Map<String, String> map, WordprocessingMLPackage template)
			throws Docx4JException, JAXBException {
		List<Object> tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

		// 1. find the table
		Tbl tempTable = getTemplateTable(tables, placeholders);
		List<Object> rows = getAllElementFromObject(tempTable, Tr.class);
		System.out.println("rows size:" + rows.size());
		// first row is header, second row is content
		// this is our template row
		Tr templateRow = (Tr) rows.get(0);
		List<?> textElements = getAllElementFromObject(templateRow, Text.class);
		for (Object object : textElements) {
			Text text = (Text) object;
			System.out.println("textValue:" + text.getValue());
			String value = map.get(text.getValue());
			text.setValue(StringUtils.isBlank(value) ? "" : value);
		}
		templateRow = (Tr) rows.get(1);
		textElements = getAllElementFromObject(templateRow, Text.class);
		for (Object object : textElements) {
			Text text = (Text) object;
			System.out.println("textValue:" + text.getValue());
			String value = map.get(text.getValue());
			text.setValue(StringUtils.isBlank(value) ? "" : value);
		}
	}

	private static void replaceAndAddTable(Tbl tempTable, List<Map<String, String>> textToAdd, int index)
			throws Docx4JException, JAXBException {
		// 1. find the table
		List<Object> rows = getAllElementFromObject(tempTable, Tr.class);
		System.out.println("rows size:" + rows.size());
		Tr templateRow = (Tr) rows.get(index);
		for (Map<String, String> replacements : textToAdd) {
			// 2 and 3 are done in this method
			addRowToTable(tempTable, templateRow, replacements);
		}
		// 4. remove the template row
		tempTable.getContent().remove(templateRow);
	}

	private static void genDecide(Tbl tempTable, List<Map<String, String>> textToAdd, int index)
			throws Docx4JException, JAXBException {
		// 1. find the table
		List<Object> rows = getAllElementFromObject(tempTable, Tr.class);
		System.out.println("rows size:" + rows.size());
		Tr templateRow = (Tr) rows.get(index);
		for (Map<String, String> replacements : textToAdd) {
			// 2 and 3 are done in this method
			addRowToTable2(tempTable, templateRow, replacements);
		}
		// 4. remove the template row
		tempTable.getContent().remove(templateRow);
	}
	
	private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
		List<Object> result = new ArrayList<Object>();
		if (obj instanceof JAXBElement)
			obj = ((JAXBElement<?>) obj).getValue();

		if (obj.getClass().equals(toSearch))
			result.add(obj);
		else if (obj instanceof ContentAccessor) {
			List<?> children = ((ContentAccessor) obj).getContent();
			for (Object child : children) {
				result.addAll(getAllElementFromObject(child, toSearch));
			}

		}
		return result;
	}

	private static Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException {
		for (Iterator<Object> iterator = tables.iterator(); iterator.hasNext();) {
			Object tbl = iterator.next();
			List<?> textElements = getAllElementFromObject(tbl, Text.class);
			for (Object text : textElements) {
				Text textElement = (Text) text;
				System.out.println("col value:" + textElement.getValue());
				if (StringUtils.equals(textElement.getValue(), templateKey))
					return (Tbl) tbl;
			}
		}
		return null;
	}

	
	private static void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) {
		Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
		List<?> ps = getAllElementFromObject(workingRow, P.class);
		System.out.println("p size:"+ps.size());
		
		List<?> textElements = getAllElementFromObject(workingRow, Text.class);
		for (Object object : textElements) {
			Text text = (Text) object;
			System.out.println("textValue:" + text.getValue());
			String replacementValue = (String) replacements.get(text.getValue());
			if (replacementValue != null) {
				System.out.println("replacement:" + replacementValue);
				text.setValue(replacementValue);
			}
		}

		reviewtable.getContent().add(workingRow);
	}
	
	
	private static void addRowToTable2(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) {
		Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
		List<?> ps = getAllElementFromObject(workingRow, P.class);
		System.out.println("p size:"+ps.size());
		for(Object obj: ps){
			P tempP = (P) obj;
			Tc tc = (Tc) tempP.getParent();
			List<?> textElements = getAllElementFromObject(tempP, Text.class);
			for (Object object : textElements) {
				Text text = (Text) object;
				String replacementValue = (String) replacements.get(text.getValue());
				if (replacementValue != null) {
					text.setValue(replacementValue);
					ObjectFactory factory = Context.getWmlObjectFactory();
					P paragraph = factory.createP();
					R run = factory.createR();
					Text x = new Text();
					x.setValue("xxxxxxxxx");
					run.getContent().add(x);
					paragraph.getContent().add(run);
					tc.getContent().add(paragraph);
//					workingRow.getContent().add(tc);
				}
			}
			
		}
		reviewtable.getContent().add(workingRow);
	}

	private static void addPageBreak(WordprocessingMLPackage template) {
		org.docx4j.wml.P p = new org.docx4j.wml.P();
		org.docx4j.wml.R r = new org.docx4j.wml.R();
		org.docx4j.wml.Br br = new org.docx4j.wml.Br();
		br.setType(STBrType.PAGE);
		r.getContent().add(br);
		p.getContent().add(r);
		template.getMainDocumentPart().addObject(p);
	}

	private static String genChineseNum(String original) {
		return StringUtils.replaceEach(original, NUM, CHINESE_NUM);
	}

	private static Relationship createFooterPart(WordprocessingMLPackage template) throws InvalidFormatException {
		FooterPart footerPart = new FooterPart();
		footerPart.setPackage(template);

		footerPart.setJaxbElement(createFooter("Text"));

		return template.getMainDocumentPart().addTargetPart(footerPart);
	}

	private static Ftr createFooter(String content) {
		ObjectFactory factory = Context.getWmlObjectFactory();
		Ftr footer = factory.createFtr();
		P paragraph = factory.createP();
		R run = factory.createR();
		Text text = new Text();
		text.setValue(content);
		run.getContent().add(text);
		paragraph.getContent().add(run);
		footer.getContent().add(paragraph);
		return footer;
	}

	private static void createFooterReference(WordprocessingMLPackage template, Relationship relationship) {
		ObjectFactory factory = Context.getWmlObjectFactory();
		List<SectionWrapper> sections = template.getDocumentModel().getSections();

		SectPr sectionProperties = sections.get(sections.size() - 1).getSectPr();
		// There is always a section wrapper, but it might not contain a sectPr
		if (sectionProperties == null) {
			sectionProperties = factory.createSectPr();
			template.getMainDocumentPart().addObject(sectionProperties);
			sections.get(sections.size() - 1).setSectPr(sectionProperties);
		}

		FooterReference footerReference = factory.createFooterReference();
		footerReference.setId(relationship.getId());
		footerReference.setType(HdrFtrRef.DEFAULT);
		sectionProperties.getEGHdrFtrReferences().add(footerReference);
	}

	private static void genDocP(WordprocessingMLPackage template) {
		ObjectFactory factory = Context.getWmlObjectFactory();
		P paragraph = factory.createP();
		R run = factory.createR();
		Text text = new Text();
		text.setValue("xxxxxxxxx");
		run.getContent().add(text);
		paragraph.getContent().add(run);
		template.getMainDocumentPart().getContent().add(paragraph);
	}

	private static P cloneP(P p, Map<String, String> replacements) {
		P tempP = (P) XmlUtils.deepCopy(p);
		List<?> textElements = getAllElementFromObject(tempP, Text.class);
		for (Object object : textElements) {
			Text text = (Text) object;
			String replacementValue = (String) replacements.get(text.getValue());
			if (replacementValue != null) {
				text.setValue(replacementValue);
			}
		}
		return tempP;
	}
	
	private void genDocP(P item1, WordprocessingMLPackage template, Map<String, String> tempMap) {
		P tempP = XmlUtils.deepCopy(item1);
		P newP = cloneP(tempP, tempMap);
		template.getMainDocumentPart().getContent().add(newP);
	}
}
